<?php
/**
* TableJoin 클래스 정의(Sybase)
*
* 테이블 객체들에 대한 조인 핸드링
* 현재 INNER JOIN 에 대해서만 구현!!
*
* @package Database
* @version 1.1.0
* @since 2008-02-13
* @update 2008-11-03
* @author hamhaja <hamhaja@nextez.co.kr>
**/
if (!class_exists("TableJoin"))
{
	class TableJoin
	{
		/**
		* @var object $_Db Sybase 클래스 객체 참조
		**/
		var $_Db;

		/**
		* @var string $_Tables 테이블 객체 목록
		**/
		var $_Tables;

		/**
		* @var array $_limit LIMIT 범위
		**/
		var $_limit;


		/**
		* PHP 5 Constructor
		**/
		function __construct(&$Db)
		{
			$this->_Db		= $Db;
			$this->_Tables	= array();
			$this->_limit	= false;

			$args = func_get_args();

			for ($i=1; $i<count($args); $i++)
			{
				$this->_Tables[] = & $args[$i];
			}
		}

		/**
		* Constructor
		*/
		function TableJoin(&$Db)
		{
			$this->__construct($Db);
		}

		/**
		* JOIN에 대한 COUNT()를 실행한다.
		* @param mixed $where 조건절 (array or string)
		* @param string $field 조회필드
		* @return integer row 수
		* @version 1.0.0
		**/
		function count($where='', $field='*')
		{
			if (!is_array($where) && !is_string($where))
				user_error('The argument should be an array or string [where]', E_USER_ERROR);
			if (!is_array($this->_Tables) && count($this->_Tables))
				user_error('Not exitst join tables', E_USER_ERROR);

			if (is_array($where)) $where = implode(' AND ', $where);
			if (!empty($where)) $where = ' WHERE ' . $where;

			$table = implode(', ', $this->get_all_table());

			$sql = 'SELECT COUNT(' . $field . ') AS c FROM ' . $table . $where;
			if ($this->_Db->query($sql))
			{
				$fetch = $this->_Db->fetch();
				$this->_Db->clear();

				return $fetch['c'];
			}
			return false;
		}

		/**
		* 하나의 레코드를 반환합니다.
		* @param mixed $field 반환필드목록, 공백인 경우는 전체필드를 반환
		* @param mixed $where 조절절, array이면 AND로 조합, string 이면 문자열 조건절
		* @param integer $fetch_type 반환형태
		* @return mixed 해당자료를 담은 정보, 자료가 없으면 false
		* @version 1.0.0
		**/
		function get_a_record($field, $where, $fetch_type=FETCH_TYPE_ASSOC)
		{
			if (!is_array($where) && !is_string($where))
				user_error('The second argument should be an array or string', E_USER_ERROR);
			if (is_array($where)) $where = implode(' AND ', $where);
			if (empty($where)) user_error('Empty value [where]', E_USER_ERROR);

			// set fields
			if (is_array($field)) $field = implode(',', $field);
			if (in_array($field, array('', '*'))) $field = implode(', ', $this->get_all_column());

			// set tables
			$table = implode(', ', $this->get_all_table());

			// 자료 패치
			$sql = 'SELECT ' . $field . ' FROM ' . $table . ' WHERE ' . $where;

			$this->_Db->query($sql);
			$return = $this->_Db->fetch($fetch_type);
			$this->_Db->clear();

			// 결과값 리턴
			return $return;
		}

		/**
		* 해당자료를 배열 형태로 반환합니다.
		* @param mixed $field 반환필드
		* @param mixed $where 검색조건절
		* @param string $order 정열대상
		* @param string $key_field KEY 선택되어질 필드
		* @param integer $fetch_type 반환형태
		* @return array 해당자료를 담은 배열
		* @version 1.0.0
		**/
		function get_list($field='', $where='', $order='', $key_field='_index', $fetch_type=FETCH_TYPE_ASSOC)
		{
			$return = array();
			$sql = '';

			// check parameter
			if (!is_string($field) && !is_array($field))
				user_error('The argument should be an string or array [field]', E_USER_ERROR);
			if (!is_string($where) && !is_array($where))
				user_error('The argument should be an string or array [where]', E_USER_ERROR);
			if (!is_string($order) && !is_array($order))
				user_error('The argument should be an string or array [order]', E_USER_ERROR);

			// set field
			if (is_array($field)) $field = implode(',', $field);
			if (in_array($field, array('', '*'))) $field = implode(', ', $this->get_all_column());

			// set table
			$table = implode(', ', $this->get_all_table());

			// set where
			if (is_array($where)) $where = implode(' AND ', $where);
			if ($where) $where = ' WHERE ' . $where;

			// set order
			if (is_array($order)) $order = implode(',', $order);
			if ($order) $order = ' ORDER BY ' . $order;

			// get list
			/*if (!is_array($this->_limit))
			{
				$sql = 'SELECT ' . $field . ' FROM ' . $table. $where . $order;
				$this->_Db->query($sql);
			}
			else
			{
				//
				// SYBASE
				//
				$temp_table_name = "tempj_" . substr(implode('_', $this->get_all_table()), 0, 20);
				$start = $this->_limit[0] + 1;
				$end = $this->_limit[0] + $this->_limit[1];
				$sql = "SET ROWCOUNT {$end}";
				$sql .= "SELECT row__index=identity(20), " . $field . " INTO #{$temp_table_name} FROM " . $table . $where . $order;
				if ($this->_Db->query($sql))
				{
					$sql = "SELECT {$field} FROM #{$temp_table_name} WHERE row__index BETWEEN {$start} AND {$end}";
					$resource = $this->_Db->query($sql);
					$this->_Db->query("DROP TABLE #{$temp_table_name}");

					$this->_Db->_resource = $resource;
				}
				else user_error("페이징 리스트 목록생성중 에러발생.", E_USER_ERROR);
			}*/
			$limit = is_array($this->_limit) ? " LIMIT {$this->_limit[0]}, {$this->_limit[1]}" : "";
			$sql = 'SELECT ' . $field . ' FROM ' . $table. $where . $order . $limit;

			$this->_Db->query($sql);
			while ($fetch = $this->_Db->fetch($fetch_type))
			{
				if ($key_field != '_index') $return[$fetch[$key_field]] = $fetch;
				else $return[] = $fetch;
			}
			$this->_Db->clear();

			return $return;
		}

		/**
		* 해당자료를 배열 형태로 반환합니다. 단, 반환필드는 only 하나만 반환된다.
		* @param string $field 반환필드
		* @param string $where 검색조건절
		* @param string $order 정열대상, 비어있는경우 Primary Key가 기준이 된다.
		* @param integer $key 키로 사용될 필드, null 이면 자동 index사용
		* @return array 해당자료를 담은 배열
		* @version 1.1.0
		**/
		function get_single_list($field='', $where='', $order='_primary', $key=null)
		{
			$list = array();

			$get_field = is_null($key) ? $field : $field . ', ' . $key;

			$tmp_list = & $this->get_list($get_field, $where, $order);
			foreach ($tmp_list as $v)
			{
				if (is_null($key)) $list[] = $v[$field];
				else $list[$v[$key]] = $v[$field];
			}

			return $list;
		}

		/**
		* 설정된 테이블객체의 전체 컬럼 목록을 반환합니다.
		* @return array 전체 컬럼 목록
		* @version 1.0.0
		**/
		function get_all_column()
		{
			$columns = array();
			if (!is_array($this->_Tables)) return $columns;

			foreach ($this->_Tables as $obj)
				$columns = array_merge($columns, array_keys($obj->_table_fields));

			return $columns;
		}

		/**
		* 설정된 테이블객체의 전체 테이블 목록을 반환합니다.
		* @return array 전체 테이블 목록
		* @version 1.0.0
		**/
		function get_all_table()
		{
			$tables = array();
			if (!is_array($this->_Tables)) return $tables;

			foreach ($this->_Tables as $obj)
			{
				$tables[] = $obj->_table();
			}

			return $tables;
		}

		/**
		* LIMIT 쿼리문을 생성하여, get_list() 호출시 적용되며, 사용후 초기화된다.
		* @param $start_row 레코드위치
		* @param $limit_row 레코드수
		* @version 1.0.0
		**/
		function limit($start_row, $limit_row)
		{
			$this->_limit = array($start_row, $limit_row);
		}

		/**
		* 페이징을 설정합니다.
		* @param object $Paging 페이징 인스턴스
		* @param string OR array $where 조건절
		* @param integer $page 현재 페이지
		* @param integer $row 페이지에 보여질 레코드 수
		* @param integer $col 페이징수
		* @version 1.0.0
		**/
		function paging(&$Paging, $where, $page, $row, $col)
		{
			if (!is_integer($row)) user_error('The argument should be an string or array [page]', E_USER_ERROR);
			if (!is_integer($row)) user_error('The argument should be an string or array [row]', E_USER_ERROR);
			if (!is_integer($row)) user_error('The argument should be an string or array [col]', E_USER_ERROR);
			if (is_array($where)) $where = implode(' AND ', $where);
			// set paging
			$Paging->set_search_num($this->count($where));
			$Paging->set_current_page($page);
			$Paging->set_row($row);
			$Paging->set_col($col);
			$this->limit(($page - 1) * $row, $row);
		}

		/**
		* Set debug
		* @version 1.0.0
		**/
		function debug() { $this->_Db->debug(); }
	}
}
?>